"""
cProfile 基础使用示例
演示最常用的性能分析方法
"""
import cProfile
import pstats
import io
from typing import Any


def fibonacci(n: int) -> int:
    """计算斐波那契数列（递归版本 - 性能较差）"""
    if n <= 1:
        return n
    return fibonacci(n - 1) + fibonacci(n - 2)


def fibonacci_optimized(n: int, memo: dict = None) -> int:
    """计算斐波那契数列（优化版本 - 带缓存）"""
    if memo is None:
        memo = {}
    
    if n in memo:
        return memo[n]
    
    if n <= 1:
        return n
    
    memo[n] = fibonacci_optimized(n - 1, memo) + fibonacci_optimized(n - 2, memo)
    return memo[n]


def slow_function() -> None:
    """模拟一个慢函数"""
    total = 0
    for i in range(1000000):
        total += i ** 2
    return total


def main_task() -> None:
    """主任务函数"""
    print("计算斐波那契数列...")
    result = fibonacci(25)
    print(f"fibonacci(25) = {result}")
    
    print("执行慢函数...")
    slow_function()
    
    print("优化版本...")
    result_opt = fibonacci_optimized(25)
    print(f"fibonacci_optimized(25) = {result_opt}")


# ============================================================================
# 方法 1: 使用 cProfile.run() - 最简单的方式
# ============================================================================
def example_1_simple_run() -> None:
    """示例1: 最简单的性能分析"""
    print("\n" + "=" * 60)
    print("示例 1: 使用 cProfile.run()")
    print("=" * 60)
    
    # 直接分析一个函数调用
    cProfile.run('main_task()')


# ============================================================================
# 方法 2: 使用 cProfile.runctx() - 传递上下文
# ============================================================================
def example_2_run_with_context() -> None:
    """示例2: 使用上下文运行"""
    print("\n" + "=" * 60)
    print("示例 2: 使用 cProfile.runctx()")
    print("=" * 60)
    
    # 准备上下文
    globals_dict = {'fibonacci': fibonacci, 'slow_function': slow_function}
    locals_dict = {'n': 20}
    
    # 运行并分析
    cProfile.runctx('fibonacci(n)', globals_dict, locals_dict)


# ============================================================================
# 方法 3: 使用 Profile 对象 - 更灵活的控制
# ============================================================================
def example_3_profile_object() -> None:
    """示例3: 使用 Profile 对象"""
    print("\n" + "=" * 60)
    print("示例 3: 使用 Profile 对象")
    print("=" * 60)
    
    # 创建 Profiler
    profiler = cProfile.Profile()
    
    # 开始分析
    profiler.enable()
    
    # 执行要分析的代码
    main_task()
    
    # 停止分析
    profiler.disable()
    
    # 打印统计信息
    profiler.print_stats()


# ============================================================================
# 方法 4: 保存分析结果到文件
# ============================================================================
def example_4_save_to_file() -> None:
    """示例4: 保存分析结果到文件"""
    print("\n" + "=" * 60)
    print("示例 4: 保存分析结果到文件")
    print("=" * 60)
    
    # 分析并保存到文件
    output_file = 'profile_results.prof'
    cProfile.run('main_task()', output_file)
    
    print(f"分析结果已保存到: {output_file}")
    print("可以使用 pstats 模块读取和分析")


# ============================================================================
# 方法 5: 使用 pstats 格式化输出
# ============================================================================
def example_5_formatted_output() -> None:
    """示例5: 使用 pstats 格式化输出"""
    print("\n" + "=" * 60)
    print("示例 5: 使用 pstats 格式化输出")
    print("=" * 60)
    
    # 创建 Profiler
    profiler = cProfile.Profile()
    profiler.enable()
    main_task()
    profiler.disable()
    
    # 创建 Stats 对象
    stats = pstats.Stats(profiler)
    
    # 排序并打印
    print("\n按累计时间排序（前10项）:")
    stats.sort_stats('cumulative').print_stats(10)
    
    print("\n按调用次数排序（前10项）:")
    stats.sort_stats('calls').print_stats(10)
    
    print("\n按内部时间排序（前10项）:")
    stats.sort_stats('time').print_stats(10)


# ============================================================================
# 方法 6: 输出到字符串
# ============================================================================
def example_6_string_output() -> str:
    """示例6: 将分析结果输出到字符串"""
    print("\n" + "=" * 60)
    print("示例 6: 输出到字符串")
    print("=" * 60)
    
    profiler = cProfile.Profile()
    profiler.enable()
    fibonacci(20)
    profiler.disable()
    
    # 重定向到字符串
    s = io.StringIO()
    stats = pstats.Stats(profiler, stream=s)
    stats.sort_stats('cumulative')
    stats.print_stats()
    
    result = s.getvalue()
    print(result)
    
    return result


# ============================================================================
# 方法 7: 装饰器方式
# ============================================================================
def profile_decorator(func):
    """性能分析装饰器"""
    def wrapper(*args, **kwargs):
        profiler = cProfile.Profile()
        profiler.enable()
        result = func(*args, **kwargs)
        profiler.disable()
        
        # 打印统计信息
        stats = pstats.Stats(profiler)
        stats.sort_stats('cumulative')
        print(f"\n性能分析: {func.__name__}")
        print("-" * 60)
        stats.print_stats(10)
        
        return result
    return wrapper


@profile_decorator
def decorated_function() -> int:
    """使用装饰器的函数"""
    return fibonacci(22)


def example_7_decorator() -> None:
    """示例7: 使用装饰器"""
    print("\n" + "=" * 60)
    print("示例 7: 使用装饰器")
    print("=" * 60)
    
    result = decorated_function()
    print(f"结果: {result}")


# ============================================================================
# 主函数
# ============================================================================
def run_all_examples() -> None:
    """运行所有示例"""
    print("cProfile 基础使用示例")
    print("=" * 60)
    
    example_1_simple_run()
    example_2_run_with_context()
    example_3_profile_object()
    example_4_save_to_file()
    example_5_formatted_output()
    example_6_string_output()
    example_7_decorator()


if __name__ == '__main__':
    run_all_examples()
